#将Excel中的道路数据转换为Python数据结构
import os
import re

import matplotlib.pyplot as plt
import numpy as np
import pandas as pd

lastMappID = 0
roadPoints = []


#初步获取道路数据
def getRoadPoints(mapID, otherMap='无'):
    global roadPoints
    global lastMappID
    if roadPoints and lastMappID == mapID: return roadPoints
    lastMappID = mapID
    # 读取Excel的“道路”工作表
    if mapID == 1:
        excel_file = '..\\data\\4-拙政园数据坐标.xlsx'
    elif mapID == 2:
        excel_file = '..\\data\\4-留园数据坐标.xlsx'
    elif mapID == 3:
        excel_file = '..\\data\\4-寄畅园数据坐标.xlsx'
    elif mapID == 4:
        excel_file = '..\\data\\4-瞻园数据坐标.xlsx'
    elif mapID == 5:
        excel_file = '..\\data\\4-豫园数据坐标.xlsx'
    elif mapID == 6:
        excel_file = '..\\data\\4-秋霞圃数据坐标.xlsx'
    elif mapID == 7:
        excel_file = '..\\data\\4-沈园数据坐标.xlsx'
    elif mapID == 8:
        excel_file = '..\\data\\4-怡园数据坐标.xlsx'
    elif mapID == 9:
        excel_file = '..\\data\\4-耦园数据坐标.xlsx'
    elif mapID == 10:
        excel_file = '..\\data\\4-绮园数据坐标.xlsx'
    else:
        excel_file = os.path.join('..\\data\\', otherMap)
    df = pd.read_excel(excel_file, sheet_name='道路')

    # 提取第一列数据（区分线段的坐标）
    raw_data = df.iloc[:, 0].dropna().astype(str)
    segments = []  # 存储所有线段
    current_segment = []  # 当前线段点列表
    segment_id = None

    for item in raw_data:
        if item.startswith('            {0;'):
            # 新线段开始：保存当前线段（如果有），并重置
            if current_segment:
                segments.append(current_segment)
            current_segment = []
            segment_id = int(re.findall(r'\d+', item)[0])  # 提取线段ID
        else:

            # 解析坐标点：格式为 "b.{x,y,z}"
            if mapID <= 10:
                match = re.match(r'(\d+)\. \{([-\d.]+), ([-\d.]+), ([-\d.]+)\}', item)
                if match:
                    b = int(match.group(1))
                    x = float(match.group(2))
                    y = float(match.group(3))
                    current_segment.append((x, y))
            else:
                match = re.match(r'\(([-\d.]+), ([-\d.]+), ([-\d.]+)\)', item)
                if match:
                    x = float(match.group(1))
                    y = float(match.group(2))
                    current_segment.append((x, y))

    # 添加最后一条线段
    if current_segment:
        segments.append(current_segment)
    return segments


#数据清洗
def getClearRoadPoints(mapID, step_size=10.0, otherMap='无'):
    segments = getRoadPoints(mapID, otherMap)
    if mapID > 10: return segments
    """
    清理线段并插值生成等间距点。
    step_size: 点间距（mm）
    """
    cleaned_segments = []
    for seg in segments:
        # 去除重复点（基于坐标）
        unique_points = []
        last_point = None
        for point in seg:
            if last_point is None or distance(point, last_point) > 10:  # 微小距离阈值
                unique_points.append(point)
            last_point = point

        # 线性插值：确保点间距一致
        if len(unique_points) < 2:
            continue  # 跳过无效线段

        interpolated_points = []
        for i in range(len(unique_points) - 1):
            start = unique_points[i]
            end = unique_points[i + 1]
            seg_length = distance(start, end)  # 计算两点距离
            num_points = int(seg_length / step_size) + 1
            for j in range(num_points):
                ratio = j / (num_points - 1) if num_points > 1 else 0
                x = start[0] + ratio * (end[0] - start[0])
                y = start[1] + ratio * (end[1] - start[1])
                interpolated_points.append((x, y))

        cleaned_segments.append(interpolated_points)

    return cleaned_segments


# 距离计算函数
def distance(p1, p2):
    return ((p1[0] - p2[0]) ** 2 + (p1[1] - p2[1]) ** 2) ** 0.5


#可视化路线图
def visualize_cleaned_data(road_points):
    plt.figure(figsize=(12, 10))
    # 绘制道路中心点序列：连线表示路径
    plt.xlim(-25000, 175000)
    plt.ylim(-10000, 160000)
    for road in road_points:
        x_road = [point[0] for point in road]
        y_road = [point[1] for point in road]
        plt.scatter(x_road, y_road, s=10, c='blue', alpha=0.5)  # 可选：显示点位置

        #plt.pause(0.001)
    # 添加图例和标签
    plt.legend(loc='upper right')
    plt.title('ROAD')
    plt.xlabel('X')
    plt.ylabel('Y')
    plt.grid(True, alpha=0.3)
    plt.axis('equal')  # 保证比例相等，避免失真

    # 添加比例尺和指北针（简单示例）
    plt.text(0.05, 0.95, 'N', transform=plt.gca().transAxes, fontsize=12, weight='bold')  # 指北针
    plt.plot([0.1, 0.1], [0.1, 0.2], 'k-', linewidth=2)  # 比例尺线段
    plt.text(0.11, 0.15, '10 m', fontsize=10)

    plt.show()


#获取转折点
def findCornerPoints(mapID, otherMap='无'):
    roadPoints = getRoadPoints(mapID, otherMap)
    cornerPoints = []
    for road_line in roadPoints:
        points = np.array(road_line)
        angles = []
        for i in range(2, len(points) - 3):
            vector_prev = points[i] - points[i - 2]
            vector_next = points[i + 2] - points[i]
            # 计算点积
            dot_product = np.dot(vector_prev, vector_next)
            # 计算模长
            norm_prev = np.linalg.norm(vector_prev)
            norm_next = np.linalg.norm(vector_next)
            # 防止除以零的错误
            if norm_prev == 0 or norm_next == 0:
                angles.append(0)  # 或者可以根据需要处理为特殊值
                continue
            # 计算余弦值 (使用数值安全的方式，确保在[-1, 1]范围内)
            cos_theta = dot_product / (norm_prev * norm_next)
            cos_theta = np.clip(cos_theta, -1.0, 1.0)  # 确保值在反余弦函数的定义域内
            # 计算角度（弧度）并转换为度数
            angle_rad = np.arccos(cos_theta)
            angle_deg = np.degrees(angle_rad)

            if angle_deg > 70:
                cornerPoints.append(road_line[i])
            angles.append(angle_deg)
    return cornerPoints

#可视化
#visualize_cleaned_data(getRoadPoints())
